import { Dispatch, Action } from 'redux';
import Axios from 'axios';

import { createAction, createAsyncAction, ActionType, createReducer } from 'typesafe-actions';
import _ from 'lodash';
import { BaseDto } from 'src/dto';

export interface WordNoteDto {
    wordNoteValue: string;
    wordNoteId: number;
}

export type WordNoteState = {
    dto: WordNoteDto
};


const setState = createAction('WORD_NOTE/SET_STATE')<WordNoteState>();

const fetchActions = createAsyncAction(
    'WORD_NOTE/FETCH/REQUEST',
    ['WORD_NOTE/FETCH/SUCCESS', (res: WordNoteDto) => res],
    ['WORD_NOTE/FETCH/FAILURE', (err: Error) => err],
    'WORD_NOTE/FETCH/CANCEL',
)();

const editActions = createAsyncAction(
    'WORD_NOTE/EDIT/REQUEST',
    ['WORD_NOTE/EDIT/SUCCESS', (res: { vo: WordNoteDto, res: BaseDto }) => res],
    ['WORD_NOTE/EDIT/FAILURE', (err: Error) => err],
    'WORD_NOTE/EDIT/CANCEL',
)();

export type WordListActions = ActionType<typeof fetchActions>
    | ActionType<typeof setState>
    | ActionType<typeof editActions>
    ;

export const fetch = (wordValue: string) =>
    async (dispatch: Dispatch) =>
        Axios.get<WordNoteDto>(`wordNote/${wordValue}`)
            .then((response) => dispatch(fetchActions.success(response.data)))


export const edit = (wordValue: string, vo: WordNoteDto) =>
    async (dispatch: Dispatch) =>
        Axios.put<BaseDto>(`wordNote/${wordValue}`, vo)
            .then(res => dispatch(editActions.success({ vo, res: res.data })))



const initialState: WordNoteState = {
    dto: {
        wordNoteId: -1,
        wordNoteValue: ''
    }
};

export const Reducer = createReducer<WordNoteState, Action>(initialState)
    .handleAction(setState, (_, action) => action.payload)
    .handleAction(fetchActions.success, (state, action) => {
        const newState = _.cloneDeep(state)
        newState.dto = action.payload
        return newState
    })
    .handleAction(editActions.success, (state, action) => {
        const newState = _.cloneDeep(state)
        action.payload.vo.wordNoteId = _.parseInt(action.payload.res.value)
        newState.dto = action.payload.vo
        return newState
    })